--[[
在 Lua 中，函数是对语句和表达式进行抽象的主要方法。既可以用来处理一些特殊的工作，也可以用来计算一些值。
Lua 提供了许多的内建函数，你可以很方便的在程序中调用它们，如print()函数可以将传入的参数打印在控制台上。
Lua 函数主要有两种用途：
    1.完成指定的任务，这种情况下函数作为调用语句使用；
    2.计算并返回值，这种情况下函数作为赋值语句的表达式使用。
Lua 编程语言函数定义格式如下：
    optional_function_scope function function_name( argument1, argument2, argument3..., argumentn)
        function_body
        return result_params_comma_separated
    end

    optional_function_scope: 该参数是可选的制定函数是全局函数还是局部函数，未设置该参数默认为全局函数，如果你需要设置函数为局部函数需要使用关键字 local。
    function_name: 指定函数名称。
    argument1, argument2, argument3..., argumentn: 函数参数，多个参数以逗号隔开，函数也可以不带参数。
    function_body: 函数体，函数中需要执行的代码语句块。
    result_params_comma_separated: 函数返回值，Lua语言函数可以返回多个值，每个值以逗号隔开。
--]]
-- 示例-比较两个值的大小，并返回最大值。
function max_value(num1, num2)
    if (num1 > num2) then
        return num1
    else
        return num2
    end
end

print(max_value(1, -19))

-- 示例-将函数作为参数
function max_value_print(num1, num2, printFun)
    printFun(max_value(num1, num2))
end

function mPrint(oaram)
    print("mPrint ", oaram)
end
max_value_print(10, 20, mPrint)

-- 示例-多返回值
-- 返回 table 中最大数和最大数下标
function max_nums(nums)
    local max_index = 1
    local max_value = nums[1]

    for i, val in ipairs(nums) do
        if (val > max_value) then
            max_value = val
            max_index = i
        end
    end

    return max_index, max_value
end

print(max_nums({1, 2, 7, 90, 32, 89, 100, 78, 902}))

-- 可变参数
-- Lua 函数可以接受可变数目的参数，和 C 语言类似，在函数参数列表中使用三点 ... 表示函数有可变的参数
function adds(...)
    local sum = 0
    for i, val in ipairs {...} do
        sum = sum + val
    end

    return sum
end

print(adds(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))

-- 可变参数长度
function length1(...)
    local args = {...}
    return #args
end

function length2(...)
    return select("#", ...)
end

print(length1(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
print(length2(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))

--[[
通常在遍历变长参数的时候只需要使用 {…}，然而变长参数可能会包含一些 nil，那么就可以用 select 函数来访问变长参数了：select('#', …) 或者 select(n, …)
    select('#', …) 返回可变参数的长度
    select(n, …) 用于访问 n 到 select('#',…) 的参数
调用select时，必须传入一个固定实参selector(选择开关)和一系列变长参数。如果selector为数字n,那么select返回它的第n个可变实参，否则只能为字符串"#",这样select会返回变长参数的总数。

需要几个固定参数加上可变参数，固定参数必须放在变长参数之前
--]]
function foo(num, ...)
    return select(num, ...)
end
print(foo(2, 1, 2, 3, 4))
print(foo(3, 1, 2, 3, 4))
